/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.task.zkex.list.tree;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.vos.datalist.ListDropVo;
import cn.easyplatform.spi.service.ListService;
import cn.easyplatform.type.DeviceType;
import cn.easyplatform.type.FieldVo;
import cn.easyplatform.type.ListRowVo;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.ext.zul.Datalist;
import cn.easyplatform.web.ext.zul.Loader;
import cn.easyplatform.web.service.ServiceLocator;
import cn.easyplatform.web.task.OperableHandler;
import cn.easyplatform.web.task.MainTaskSupport;
import cn.easyplatform.web.task.support.ManagedComponent;
import cn.easyplatform.web.task.support.SupportFactory;
import cn.easyplatform.web.task.support.scripting.CompliableScriptEngine;
import cn.easyplatform.web.task.zkex.DropSupport;
import cn.easyplatform.web.task.zkex.list.OperableListSupport;
import cn.easyplatform.web.task.zkex.list.PanelSupport;
import cn.easyplatform.web.task.zkex.list.menu.SimpleColumnMenu;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class LoaderTreeBuilder extends AbstractSelectableTreeBuilder<Loader> {

    private Window window;

    private List<FieldVo[]> targetData;

    private CompliableScriptEngine engine;

    /**
     * @param mainTaskHandler
     * @param listExt
     * @param ref
     */
    public LoaderTreeBuilder(OperableHandler mainTaskHandler, Datalist listExt,
                             Loader ref, Component anchor) {
        super(mainTaskHandler, listExt, ref, anchor);
    }

    protected Component createContent() {
        Component c = super.createContent();
        window = new Window();
        window.setTitle(layout.getName());
        window.setMaximizable(true);
        window.setBorder(true);
        window.setClosable(true);
        if (!Strings.isBlank(getEntity().getHeight()))
            window.setHeight(getEntity().getHeight());
        else
            window.setHeight("550px");
        if (!Strings.isBlank(getEntity().getWidth()))
            window.setWidth(getEntity().getWidth());
        else
            window.setWidth("650px");
        window.setSizable(true);
        window.addEventListener(Events.ON_CLOSE, this);
        window.appendChild(c);
        if (ref.isMultiple()) {
            clickType = 0;
        } else {
            clickType = 2;
            if (!Strings.isBlank(ref.getTarget()))
                listExt.setEvent("select()");
        }
        if (!Strings.isBlank(ref.getValidator())
                && !Strings.isBlank(ref.getTarget())) {
            for (ManagedComponent target : ((MainTaskSupport) getMainHandler())
                    .getManagedEntityComponents()) {
                if (target.getComponent().getId().equals(ref.getTarget())) {
                    if (target instanceof OperableListSupport) {
                        OperableListSupport os = (OperableListSupport) target;
                        targetData = os.getData(false, false);
                        break;
                    }
                }
            }
            if (targetData != null) {
                engine = SupportFactory.getCompliableScriptEngine(this);
                engine.compile(ref.getValidator());
            }
        }
        listExt.setAttribute("ref", ref);
        return window;
    }

    @Override
    public void select(Event evt) {
        if (listExt.getSelectedCount() < 1)
            return;
        MainTaskSupport mts = null;
        if (getMainHandler() instanceof PanelSupport) {
            mts = (MainTaskSupport) ((PanelSupport) getMainHandler()).getList().getMainHandler().getParent();
        } else
            mts = (MainTaskSupport) getMainHandler();
        for (ManagedComponent target : mts.getManagedEntityComponents()) {
            if (target.getComponent().getId().equals(ref.getTarget())) {
                if (listExt.getSelectedCount() > 0) {
                    List<ListRowVo> data = new ArrayList<ListRowVo>();
                    for (Treeitem li : listExt.getSelectedItems()) {
                        if (li.getValue() != null
                                && li.getValue() instanceof ListRowVo && !validate(li))
                            data.add(li.getValue());
                    }
                    if (!data.isEmpty()) {
                        ListDropVo vo = new ListDropVo(ref.getFilter(),
                                ref.getId(), data);
                        if (target instanceof DropSupport) {
                            DropSupport os = (DropSupport) target;
                            Events.postEvent(new Event(Events.ON_USER, ref,
                                    "onBefore"));
                            os.drop(vo);
                            Events.postEvent(new Event(Events.ON_USER, ref,
                                    "onAfter"));
                        }
                    }
                }
                break;
            }
        }
        close();
    }

    @Override
    protected void close() {
        if (engine != null)
            engine.destroy();
        engine = null;
        targetData = null;
        ListService dls = ServiceLocator
                .lookup(ListService.class);
        dls.doClose(new SimpleRequestMessage(mainTaskHandler.getId(), listExt
                .getId()));
        window.detach();
        window = null;
    }

    @Override
    protected void setMenupopup(HtmlBasedComponent head) {
        if (Contexts.getEnv().getDeviceType().equalsIgnoreCase(DeviceType.AJAX.getName())) {
            Menupopup popup = new SimpleColumnMenu(head, this, getEntity()
                    .isExport(), getEntity().isPrint());
            popup.setId(listExt.getId() + "_popup");
            window.appendChild(popup);
            List<Treecol> headers = head.getChildren();
            for (Treecol header : headers)
                header.setContext(popup);
            head.setAttribute("menupopup", "");
        }
    }

    @Override
    public boolean validate(Component c) {
        Treeitem item = (Treeitem) c;
        if (engine != null) {
            ListRowVo rv = item.getValue();
            FieldVo[] source = castTo(rv);
            for (FieldVo[] target : targetData) {
                Object obj = engine.eval(source, target);
                if (obj != null && obj instanceof Boolean && (Boolean) obj) {
                    if (ref.isMultiple() && ref.isCheckmark())
                        item.setSelected(true);
                    else
                        item.setVisible(false);
                    return true;
                }
            }
        }
        return false;
    }

}
